#ifndef OBJQUEUE_H_INCLUDED
#define OBJQUEUE_H_INCLUDED

#include "mutex.h"
#include "event.h"
#include <map>
#include <list>

using std::map;
using std::list;

template < typename key, typename obj>
class MapQueue
{
public:
    MapQueue()
    {}

    void enqueue(const key& k, const obj& o)
    {
        ScopedMutex lock(&m_mutex);
        m_objs[k] = o;
        m_event.set();
    }
    
    void dequeue(const key& k)
    {
        ScopedMutex lock(&m_mutex);
        typename map<key,obj>::iterator it = m_objs.find(k);
        if ( it != m_objs.end())
            m_objs.erase(it);
    }

    void get(const key& k, obj& o, bool bdel = false)
    {
        ScopedMutex lock(&m_mutex);
        typename map<key,obj>::iterator it = m_objs.find(k);
        if ( it != m_objs.end())
        {
            o = it->second;
            if (bdel)
                m_objs.erase(it);
        }
    }

	// may cause mem leak if m_objs's members are pointers
    void clear()
    {
        ScopedMutex lock(&m_mutex);
        m_objs.clear();
        m_event.reset();
    }

    void wait()
    {
        m_event.wait();
    }

    unsigned long size()
    {
        ScopedMutex lock(&m_mutex);
        return m_objs.size();
    }
private:
    map<key,obj>    m_objs;
    Mutex           m_mutex;
    Event           m_event;
};

template < typename obj>
class ListQueue
{
public:
    ListQueue()
    {}
    
    void pop_front(obj& o)
    {
        ScopedMutex lock(&m_mutex);
        if ( m_objs.empty() )
            return;

        o = m_objs.front();
        m_objs.pop_front();
    }
    
    void pop_back(obj& o)
    {
        ScopedMutex lock(&m_mutex);
        if ( m_objs.empty() )
            return;

        o = m_objs.back();
        m_objs.pop_back();
    }

    void push_back(const obj& o)
    {
        ScopedMutex lock(&m_mutex);
        m_objs.push_back(o);
        m_event.set();
    }
    
    void push_front(const obj& o)
    {
        ScopedMutex lock(&m_mutex);
        m_objs.push_front(o);
        m_event.set();
    }
    
	// may cause mem leak if m_objs's members are pointers
    void clear()
    {
        ScopedMutex lock(&m_mutex);
        m_objs.clear();
        m_event.reset();
    }

    void wait()
    {
        m_event.wait();
    }

    unsigned long size()
    {
        ScopedMutex lock(&m_mutex);
        return m_objs.size();
    }
private:
    list<obj>       m_objs;
    Mutex           m_mutex;
    Event           m_event;
};

#endif




